home *** CD-ROM | disk | FTP | other *** search
/ Amiga Plus 1999 #2 / Amiga Plus CD - 1999 - No. 2.iso / System-Boost / Workbench / ToolManager / Source / Library / config.c < prev    next >
C/C++ Source or Header  |  1998-06-17  |  11KB  |  476 lines

  1. /*
  2.  * config.c  V3.1
  3.  *
  4.  * ToolManager configuration file handling routines
  5.  *
  6.  * Copyright (C) 1990-98 Stefan Becker
  7.  *
  8.  * This source code is for educational purposes only. You may study it
  9.  * and copy ideas or algorithms from it for your own projects. It is
  10.  * not allowed to use any of the source codes (in full or in parts)
  11.  * in other programs. Especially it is not allowed to create variants
  12.  * of ToolManager or ToolManager-like programs from this source code.
  13.  *
  14.  */
  15.  
  16. #include "toolmanager.h"
  17.  
  18. /* Global data */
  19. struct Library *IFFParseBase                  = NULL;
  20.  
  21. /* Local data */
  22. static const char            ConfigFileName[] = "ENV:" TMCONFIGNAME;
  23. static struct IFFHandle     *ConfigIFFHandle  = NULL;
  24. static ULONG                 ConfigOpen       = FALSE;
  25. static ULONG                 CurrentType;
  26. static struct NotifyRequest  ConfigNotify     = {ConfigFileName, NULL, 0,
  27.  NRF_SEND_SIGNAL | NRF_NOTIFY_INITIAL, NULL};
  28.  
  29. /* Start configuration file change notification */
  30. #define DEBUGFUNCTION StartConfigChangeNotify
  31. LONG StartConfigChangeNotify(void)
  32. {
  33.  LONG signal;
  34.  
  35.  CONFIG_LOG(LOG0(Entry))
  36.  
  37.  /* Allocate Signal for file notification */
  38.  if ((signal = AllocSignal(-1)) != -1) {
  39.  
  40.   CONFIG_LOG(LOG1(Signal,"%ld", signal))
  41.  
  42.   /* Initialize notify request */
  43.   ConfigNotify.nr_stuff.nr_Signal.nr_Task      = FindTask(NULL);
  44.   ConfigNotify.nr_stuff.nr_Signal.nr_SignalNum = signal;
  45.  
  46.   /* Start notification */
  47.   if (StartNotify(&ConfigNotify) == FALSE) {
  48.  
  49.    CONFIG_LOG(LOG0(Failed))
  50.  
  51.    /* Notification failed */
  52.    FreeSignal(signal);
  53.    signal = -1;
  54.   }
  55. #ifdef DEBUG
  56.   else CONFIG_LOG(LOG0(Started))
  57. #endif
  58.  }
  59.  
  60.  return(signal);
  61. }
  62.  
  63. /* Stop configuration file parsing */
  64. #undef  DEBUGFUNCTION
  65. #define DEBUGFUNCTION StopConfigParse
  66. static void StopConfigParse(void)
  67. {
  68.  CONFIG_LOG(LOG0(Entry))
  69.  
  70.  /* IFF parser library open? */
  71.  if (IFFParseBase) {
  72.  
  73.   CONFIG_LOG(LOG1(Library, "0x%08lx", IFFParseBase))
  74.  
  75.   /* Handle allocated? */
  76.   if (ConfigIFFHandle) {
  77.  
  78.    CONFIG_LOG(LOG1(IFFHandle, "0x%08lx", ConfigIFFHandle))
  79.  
  80.    /* Configuration file open? */
  81.    if (ConfigIFFHandle->iff_Stream) {
  82.  
  83.     CONFIG_LOG(LOG1(File, "0x%08lx", ConfigIFFHandle->iff_Stream))
  84.  
  85.     /* IFF handle open? */
  86.     if (ConfigOpen) {
  87.  
  88.      CONFIG_LOG(LOG0(Config open))
  89.  
  90.      /* Close IFF handle */
  91.      CloseIFF(ConfigIFFHandle);
  92.      ConfigOpen = FALSE;
  93.     }
  94.  
  95.     /* Close file */
  96.     Close(ConfigIFFHandle->iff_Stream);
  97.    }
  98.  
  99.    /* Free IFF handle */
  100.    FreeIFF(ConfigIFFHandle);
  101.    ConfigIFFHandle = NULL;
  102.   }
  103.  
  104.   /* Close library */
  105.   CloseLibrary(IFFParseBase);
  106.   IFFParseBase = NULL;
  107.  }
  108. }
  109.  
  110. /* Stop configuration file change notification */
  111. #undef  DEBUGFUNCTION
  112. #define DEBUGFUNCTION StopConfigChangeNotify
  113. void StopConfigChangeNotify(void)
  114. {
  115.  CONFIG_LOG(LOG0(Entry))
  116.  
  117.  /* Stop configuration file parsing */
  118.  StopConfigParse();
  119.  
  120.  /* Stop notification */
  121.  EndNotify(&ConfigNotify);
  122.  FreeSignal(ConfigNotify.nr_stuff.nr_Signal.nr_SignalNum);
  123.  
  124.  CONFIG_LOG(LOG0(Exit))
  125. }
  126.  
  127. /* Handle configuration file changes */
  128. #undef  DEBUGFUNCTION
  129. #define DEBUGFUNCTION HandleConfigChange
  130. BOOL HandleConfigChange(void)
  131. {
  132.  BOOL rc = FALSE;
  133.  
  134.  /*
  135.   * NOTE: Notification happens only when the changed file has been closed.
  136.   *       But the file can't be changed while we are still reading it. Thus
  137.   *       this function can ONLY be called when we are not currently reading
  138.   *       in the configuration file.
  139.   */
  140.  
  141.  CONFIG_LOG(LOG0(Configuration has changed))
  142.  
  143.  /* Open IFF parser library */
  144.  if (IFFParseBase = OpenLibrary("iffparse.library", 39)) {
  145.  
  146.   CONFIG_LOG(LOG1(IFFParse open, "0x%08lx", IFFParseBase))
  147.  
  148.   /* Allocate IFF handle */
  149.   if (ConfigIFFHandle = AllocIFF()) {
  150.  
  151.    CONFIG_LOG(LOG1(IFFHandle, "0x%08lx", ConfigIFFHandle))
  152.  
  153.    /* Open configuration file */
  154.    if (ConfigIFFHandle->iff_Stream = Open(ConfigFileName, MODE_OLDFILE)) {
  155.  
  156.     CONFIG_LOG(LOG1(File, "0x%08lx", ConfigIFFHandle->iff_Stream))
  157.  
  158.     /* Initialize IFF handle */
  159.     InitIFFasDOS(ConfigIFFHandle);
  160.  
  161.     /* Open IFF handle */
  162.     if (OpenIFF(ConfigIFFHandle, IFFF_READ) == 0) {
  163.  
  164.      CONFIG_LOG(LOG0(Handle open))
  165.  
  166.      /* Set open flag */
  167.      ConfigOpen = TRUE;
  168.  
  169.      /* Start IFF parsing */
  170.      if (ParseIFF(ConfigIFFHandle, IFFPARSE_STEP) == 0) {
  171.       struct ContextNode *cn;
  172.  
  173.       CONFIG_LOG(LOG0(First parse step))
  174.  
  175.       /* a) Check IFF type: FORM TMPR */
  176.       /* b) Step to version chunk     */
  177.       if ((cn = CurrentChunk(ConfigIFFHandle)) &&
  178.           (cn->cn_ID == ID_FORM) && (cn->cn_Type == ID_TMPR) &&
  179.           (ParseIFF(ConfigIFFHandle, IFFPARSE_STEP) == 0) &&
  180.           (cn = CurrentChunk(ConfigIFFHandle)) &&
  181.           (cn->cn_ID == ID_FVER) && (cn->cn_Size == sizeof(TMCONFIGVERSION))) {
  182.        char *buf;
  183.  
  184.        CONFIG_LOG(LOG0(Version chunk found))
  185.  
  186.        /* Allocate memory for version chunk */
  187.        if (buf = GetMemory(sizeof(TMCONFIGVERSION))) {
  188.  
  189.         /* Read version chunk and check version */
  190.         if ((ReadChunkBytes(ConfigIFFHandle, buf, sizeof(TMCONFIGVERSION))
  191.               == sizeof(TMCONFIGVERSION)) &&
  192.             (strcmp(buf, TMCONFIGVERSION) == 0) &&
  193.             (ParseIFF(ConfigIFFHandle, IFFPARSE_STEP) == IFFERR_EOC)) {
  194.  
  195.          CONFIG_LOG(LOG0(Configuration file OK))
  196.  
  197.          /* Next FORM must be global parameters */
  198.          CurrentType = ID_TMGP;
  199.  
  200.          /* Configuration file passed the tests */
  201.          rc = TRUE;
  202.         }
  203.  
  204.         /* Free version chunk */
  205.         FreeMemory(buf, sizeof(TMCONFIGVERSION));
  206.        }
  207.       }
  208.      }
  209.     }
  210.    }
  211.   }
  212.  
  213.   /* Error while opening configuration file? */
  214.   if (rc == FALSE) StopConfigParse();
  215.  }
  216.  
  217.  CONFIG_LOG(LOG1(Result, "%ld", rc))
  218.  
  219.  return(rc);
  220. }
  221.  
  222. /* Skip an unkown chunk */
  223. #ifdef DEBUG
  224. #define SkipUnknownChunk(type, cn) _SkipUnknownChunk(type, cn)
  225. #undef  DEBUGFUNCTION
  226. #define DEBUGFUNCTION SkipUnknownChunk
  227. static BOOL _SkipUnknownChunk(ULONG type, struct ContextNode *cn)
  228. {
  229.  BOOL rc = TRUE;
  230.  
  231.  switch (type) {
  232.   case 0:
  233.    CONFIG_LOG(LOG3(Unknown Chunk, "ID 0x%08lx Type 0x%08lx Size %ld",
  234.                    cn->cn_ID, cn->cn_Type, cn->cn_Size))
  235.    break;
  236.  
  237.   case 1:
  238.    CONFIG_LOG(LOG2(Ignoring PROP, "Type 0x%08lx Size %ld",
  239.                    cn->cn_Type, cn->cn_Size))
  240.    break;
  241.  
  242.   case 2:
  243.    CONFIG_LOG(LOG2(Unexpected FORM, "Type 0x%08lx Size %ld",
  244.                    cn->cn_Type, cn->cn_Size))
  245.    break;
  246.  
  247.   case 3:
  248.    CONFIG_LOG(LOG2(Unknown FORM, "Type 0x%08lx Size %ld",
  249.                    cn->cn_Type, cn->cn_Size))
  250.    break;
  251.  }
  252.  
  253. #else
  254. #define SkipUnknownChunk(type, cn) _SkipUnknownChunk(cn)
  255. static BOOL _SkipUnknownChunk(struct ContextNode *cn)
  256. {
  257.  BOOL rc = TRUE;
  258. #endif
  259.  
  260.  /* Skip chunk */
  261.  if ((StopOnExit(ConfigIFFHandle, cn->cn_Type, cn->cn_ID) != 0) ||
  262.      (ParseIFF(ConfigIFFHandle, IFFPARSE_SCAN) != IFFERR_EOC)) {
  263.  
  264.   CONFIG_LOG(LOG0(Cannot skip unknown chunk))
  265.  
  266.   rc = FALSE;
  267.  }
  268.  
  269.  return(rc);
  270. }
  271.  
  272. /* Create an ToolManager object from an IFF FORM chunk */
  273. #undef  DEBUGFUNCTION
  274. #define DEBUGFUNCTION CreateObjectFromFORM
  275. static BOOL CreateObjectFromFORM(struct TMHandle *tmh, ULONG type)
  276. {
  277.  Object *obj;
  278.  BOOL    rc  = FALSE;
  279.  
  280.  /* Create ToolManager object */
  281.  if (obj = CreateToolManagerObject(tmh, type)) {
  282.  
  283.   CONFIG_LOG(LOG1(Object, "0x%08lx", obj))
  284.  
  285.   /* Let the object parse the FORM chunk */
  286.   if (DoMethod(obj, TMM_ParseIFF, ConfigIFFHandle) == FALSE) {
  287.  
  288.    CONFIG_LOG(LOG0(IFF Parse failed))
  289.  
  290.    /* Delete object */
  291.    DisposeObject(obj);
  292.   }
  293.  
  294.   /* All OK (ignore that object parsing might fail) */
  295.   rc = TRUE;
  296.  }
  297.  
  298.  return(rc);
  299. }
  300.  
  301. /* Parse next configuration element */
  302. #undef  DEBUGFUNCTION
  303. #define DEBUGFUNCTION NextConfigParseStep
  304. BOOL NextConfigParseStep(struct TMHandle *tmh)
  305. {
  306.  BOOL rc = TRUE;
  307.  
  308.  /* Next parse step */
  309.  switch (ParseIFF(ConfigIFFHandle, IFFPARSE_STEP)) {
  310.  
  311.   case 0: {
  312.     struct ContextNode *cn;
  313.  
  314.     if (cn = CurrentChunk(ConfigIFFHandle))
  315.  
  316.      /* Which chunk type? */
  317.      switch (cn->cn_ID) {
  318.       case ID_LIST:
  319.  
  320.        CONFIG_LOG(LOG2(Enter LIST, "Type 0x%08lx Size %ld",
  321.                        cn->cn_Type, cn->cn_Size))
  322.  
  323.        /* Store the type */
  324.        CurrentType = cn->cn_Type;
  325.        break;
  326.  
  327.       case ID_PROP:
  328.        /* Ignore PROP chunks */
  329.        rc = SkipUnknownChunk(1, cn);
  330.        break;
  331.  
  332.       case ID_FORM:
  333.  
  334.        CONFIG_LOG(LOG2(Enter FORM, "Type 0x%08lx Size %ld",
  335.                        cn->cn_Type, cn->cn_Size))
  336.  
  337.        /* Is the type correct? */
  338.        if (cn->cn_Type == CurrentType) {
  339.  
  340.         /* Yes, which FORM type? */
  341.         switch (cn->cn_Type) {
  342.          case ID_TMGP:
  343.           rc = ParseGlobalIFF(ConfigIFFHandle);
  344.           break;
  345.  
  346.          case ID_TMEX:
  347.           rc = CreateObjectFromFORM(tmh, TMOBJTYPE_EXEC);
  348.           break;
  349.  
  350.          case ID_TMIM:
  351.           rc = CreateObjectFromFORM(tmh, TMOBJTYPE_IMAGE);
  352.           break;
  353.  
  354.          case ID_TMSO:
  355.           rc = CreateObjectFromFORM(tmh, TMOBJTYPE_SOUND);
  356.           break;
  357.  
  358.          case ID_TMMO:
  359.           rc = CreateObjectFromFORM(tmh, TMOBJTYPE_MENU);
  360.           break;
  361.  
  362.          case ID_TMIC:
  363.           rc = CreateObjectFromFORM(tmh, TMOBJTYPE_ICON);
  364.           break;
  365.  
  366.          case ID_TMDO:
  367.           rc = CreateObjectFromFORM(tmh, TMOBJTYPE_DOCK);
  368.           break;
  369.  
  370.          case ID_TMAC:
  371.           rc = CreateObjectFromFORM(tmh, TMOBJTYPE_ACCESS);
  372.           break;
  373.  
  374.          default:
  375.           /* Expected, but unknown FORM type */
  376.           rc = SkipUnknownChunk(3, cn);
  377.           break;
  378.         }
  379.  
  380.        } else
  381.         /* Unexpected FORM type */
  382.         rc = SkipUnknownChunk(2, cn);
  383.        break;
  384.  
  385.       default:
  386.        /* No LIST/PROP/FORM */
  387.        rc = SkipUnknownChunk(0, cn);
  388.        break;
  389.      }
  390.  
  391.     else {
  392.      CONFIG_LOG(LOG0(No current chunk?!?))
  393.  
  394.      rc = FALSE;
  395.     }
  396.    }
  397.    break;
  398.  
  399.   case IFFERR_EOC:
  400. #ifdef DEBUG
  401.    {
  402.     struct ContextNode *cn;
  403.  
  404.     if (cn = CurrentChunk(ConfigIFFHandle))
  405.  
  406.      switch(cn->cn_ID) {
  407.       case ID_LIST:
  408.        CONFIG_LOG(LOG2(Leave LIST, "Type 0x%08lx Size %ld",
  409.                        cn->cn_Type, cn->cn_Size))
  410.        break;
  411.  
  412.       case ID_FORM:
  413.        CONFIG_LOG(LOG2(Leave FORM, "Type 0x%08lx Size %ld",
  414.                        cn->cn_Type, cn->cn_Size))
  415.        break;
  416.  
  417.       default:
  418.        CONFIG_LOG(LOG3(Leave unknown context,
  419.                        "ID 0x%08lx Type 0x%08lx Size %ld",
  420.                        cn->cn_ID, cn->cn_Type, cn->cn_Size))
  421.        break;
  422.      }
  423.    }
  424. #endif
  425.    break;
  426.  
  427. #ifdef DEBUG
  428.   case IFFERR_EOF:
  429.    CONFIG_LOG(LOG0(End of configuration reached))
  430.  
  431.    rc = FALSE;
  432.    break;
  433. #endif
  434.  
  435.   default:
  436.     CONFIG_LOG(LOG0(Error in parsing))
  437.  
  438.     rc = FALSE;
  439.     break;
  440.  }
  441.  
  442.  /* Stop parsing? */
  443.  if (rc == FALSE) StopConfigParse();
  444.  
  445.  CONFIG_LOG(LOG1(Result, "%ld", rc))
  446.  
  447.  return(rc);
  448. }
  449.  
  450. #undef  DEBUGFUNCTION
  451. #define DEBUGFUNCTION DuplicateProperty
  452. void *DuplicateProperty(struct IFFHandle *iffh, ULONG type, ULONG id)
  453. {
  454.  void                  *rc = NULL;
  455.  struct StoredProperty *sp;
  456.  
  457.  CONFIG_LOG(LOG3(Entry, "Handle 0x%08lx Type 0x%08lx ID 0x%08lx",
  458.                  iffh, type, id))
  459.  
  460.  /* Find property */
  461.  if (sp = FindProp(iffh, type, id)) {
  462.  
  463.   CONFIG_LOG(LOG2(Property, "Data 0x%08lx Size %ld", sp->sp_Data, sp->sp_Size))
  464.  
  465.   /* Allocate memory for property */
  466.   if (rc = GetVector(sp->sp_Size))
  467.  
  468.    /* Copy property */
  469.    CopyMem(sp->sp_Data, rc, sp->sp_Size);
  470.  }
  471.  
  472.  CONFIG_LOG(LOG1(Result, "0x%08lx", rc))
  473.  
  474.  return(rc);
  475. }
  476.